package com.example.wdt.wdt.statistics;

import cn.wangdian.erp.sdk.Client;
import cn.wangdian.erp.sdk.Pager;
import cn.wangdian.erp.sdk.api.aftersales.RefundAPI;
import cn.wangdian.erp.sdk.api.aftersales.dto.RefundSearchRequest;
import cn.wangdian.erp.sdk.api.aftersales.dto.RefundSearchResponse;
import cn.wangdian.erp.sdk.api.sales.StockOutAPI;
import cn.wangdian.erp.sdk.api.sales.dto.StockOutQueryRequest;
import cn.wangdian.erp.sdk.api.sales.dto.StockOutQueryResponse;
import cn.wangdian.erp.sdk.api.setting.SettingAPI;
import cn.wangdian.erp.sdk.api.wms.stockin.StockinAPI;
import cn.wangdian.erp.sdk.api.wms.stockout.StockoutAPI2;
import cn.wangdian.erp.sdk.api.wms.stockin.dto.RefundStockinRequest;
import cn.wangdian.erp.sdk.api.wms.stockin.dto.RefundStockinResponse;
import cn.wangdian.erp.sdk.api.wms.stockout.dto.SalesStockoutPositionRequest;
import cn.wangdian.erp.sdk.api.wms.stockout.dto.SalesStockoutPositionResponse;
import cn.wangdian.erp.sdk.impl.ApiFactory;
import com.example.wdt.common.utils.StringUtils;
import com.example.wdt.wdt.statistics.dto.StatisticsResultDTO;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SalesStatisticsService {

    public List<StatisticsResultDTO> queryStatistics(Client client, LocalDateTime date) {
        //分割时间段
        List<LocalDateTime[]> segments = new ArrayList<>();
        LocalDateTime startTime = date.with(LocalTime.MIDNIGHT);
        LocalDateTime endTime = startTime.plusDays(1).minusSeconds(1);
        LocalDateTime currentStart = startTime;
        boolean go = true;
        while (go) {
            LocalDateTime currentEnd = currentStart.plusMinutes(60);
            if (currentEnd.isAfter(endTime)) {
                currentEnd = endTime;
                go = false;
            }
            if (!currentStart.equals(currentEnd)) {
                segments.add(new LocalDateTime[]{currentStart, currentEnd});
            }
            currentStart = currentEnd;
        }
        //查询销售出库单(使用分割后的时间段)
        StockOutAPI stockOutAPI = ApiFactory.get(client, StockOutAPI.class);
        List<StockOutQueryResponse.OrderItem> orderItemList = new ArrayList<StockOutQueryResponse.OrderItem>();
        for (LocalDateTime[] time : segments) {
            List<StockOutQueryResponse.OrderItem> orderItems = queryWithDetail(stockOutAPI, time);
            orderItemList.addAll(orderItems);
        }
//        //查询销售出库明细(含淘系数据)(使用分割后的时间段)
//        StockoutAPI2 stockOutAPI2=ApiFactory.get(client,StockoutAPI2.class);
//        List<SalesStockoutPositionResponse.OrderInfoDto> orderInfoDtoList=new ArrayList<>();
//        for(LocalDateTime[] time:segments){
//            List<SalesStockoutPositionResponse.OrderInfoDto> orderItems=queryStockoutDetail(stockOutAPI2, time);
//        }
//        //过滤淘系数据
//        List<SalesStockoutPositionResponse.OrderInfoDto> filterOrder=filterOrder(orderInfoDtoList,orderItemList);
        //查询退货入库单
        List<RefundStockinResponse.OrderInfoDto> refundStockinOrderDtoList = queryRefundStockin(client, startTime, endTime);
        //查询退换单(仅退款)
        List<RefundSearchResponse.RefundOrderDto> refundOrderList=queryRefund(client,startTime,endTime);
        //统计数据
        List<StatisticsResultDTO> result = doStatistics(orderItemList, refundStockinOrderDtoList,refundOrderList,null);
        //检查数据完备性
        SettingAPI settingAPI = ApiFactory.get(client, SettingAPI.class);
        result.forEach(statisticsResultDTO -> {
            statisticsResultDTO.setDate(startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        });

        return result;

    }

    //查询销售出库单(不含淘系数据，含店铺字段)
    private List<StockOutQueryResponse.OrderItem> queryWithDetail(StockOutAPI stockOutAPI, LocalDateTime[] time) {
        StockOutQueryRequest stockOutQueryRequest = new StockOutQueryRequest();
        stockOutQueryRequest.setStartTime(time[0].format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        stockOutQueryRequest.setEndTime(time[1].format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        //计算总页数
        StockOutQueryResponse responseCalcTotal = stockOutAPI.query(stockOutQueryRequest, new Pager(1, 0, true));
        int totalPages = (int) Math.ceil((double) responseCalcTotal.getTotalCount() / 200);
        //执行分页查询
        List<StockOutQueryResponse.OrderItem> orderItemList = new ArrayList<StockOutQueryResponse.OrderItem>();
        for (int pageNo = totalPages - 1; pageNo >= 0; pageNo--) {
            StockOutQueryResponse response = stockOutAPI.query(stockOutQueryRequest, new Pager(200, pageNo, false));
            List<StockOutQueryResponse.OrderItem> pageOrderItems = response.getOrders();
            orderItemList.addAll(pageOrderItems);
        }

        return orderItemList;
    }

    //查询销售出库单实际明细(含淘系数据，不含店铺字段)
    private List<SalesStockoutPositionResponse.OrderInfoDto> queryStockoutDetail(StockoutAPI2 stockOutAPI2, LocalDateTime[] time)
    {
        SalesStockoutPositionRequest stockOutQueryRequest = new SalesStockoutPositionRequest();
        stockOutQueryRequest.setStartTime(time[0].format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        stockOutQueryRequest.setEndTime(time[1].format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        //计算总页数
        SalesStockoutPositionResponse responseCalcTotal = stockOutAPI2.searchPosition(stockOutQueryRequest, new Pager(1, 0, true));
        int totalPages = (int) Math.ceil((double) responseCalcTotal.getTotal() / 200);
        //执行分页查询
        List<SalesStockoutPositionResponse.OrderInfoDto> orderItemList = new ArrayList<>();
        for (int pageNo = totalPages - 1; pageNo >= 0; pageNo--) {
            SalesStockoutPositionResponse response = stockOutAPI2.searchPosition(stockOutQueryRequest, new Pager(200, pageNo, false));
            List<SalesStockoutPositionResponse.OrderInfoDto> pageOrderItems = response.getOrderList();
            orderItemList.addAll(pageOrderItems);
        }

        return orderItemList;
    }

    //过滤淘系数据
    private List<SalesStockoutPositionResponse.OrderInfoDto> filterOrder(List<SalesStockoutPositionResponse.OrderInfoDto> stockoutDetail,List<StockOutQueryResponse.OrderItem> orderItemList)
    {
        Set<Integer> stockoutIds = orderItemList.stream()
                .map(orderItem -> orderItem.getStockoutId())
                .collect(Collectors.toSet());
        List<SalesStockoutPositionResponse.OrderInfoDto> result = stockoutDetail.stream()
                .filter(order -> !stockoutIds.contains(order.getStockoutId()))
                .collect(Collectors.toList());
        return result;
    }

    //查询退货入库单
    private List<RefundStockinResponse.OrderInfoDto> queryRefundStockin(Client client, LocalDateTime startTime, LocalDateTime endTime) {
        StockinAPI stockinAPI = ApiFactory.get(client, StockinAPI.class);
        RefundStockinRequest refundStockinRequest = new RefundStockinRequest();
        refundStockinRequest.setTimeType(1);
        refundStockinRequest.setStartTime(startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        refundStockinRequest.setEndTime(endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        //计算总页数
        RefundStockinResponse responseCalcTotal = stockinAPI.searchRefund(refundStockinRequest, new Pager(1, 0, true));
        int totalPages = (int) Math.ceil((double) responseCalcTotal.getTotal() / 200);
        //执行分页查询
        List<RefundStockinResponse.OrderInfoDto> orderItemList = new ArrayList<>();
        for (int pageNo = totalPages - 1; pageNo >= 0; pageNo--) {
            RefundStockinResponse response = stockinAPI.searchRefund(refundStockinRequest, new Pager(200, pageNo, false));
            List<RefundStockinResponse.OrderInfoDto> pageOrderItems = response.getOrders();
            orderItemList.addAll(pageOrderItems);
        }

        return orderItemList;
    }

    //查询退换单(仅退款)
    private List<RefundSearchResponse.RefundOrderDto> queryRefund(Client client, LocalDateTime startTime, LocalDateTime endTime) {
        RefundAPI refundAPIAPI = ApiFactory.get(client, RefundAPI.class);
        RefundSearchRequest refundSearchRequest = new RefundSearchRequest();
        refundSearchRequest.setType((byte) 4);
        refundSearchRequest.setSettleFrom(startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        refundSearchRequest.setSettleTo(endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        //计算总页数
        RefundSearchResponse responseCalcTotal = refundAPIAPI.search(refundSearchRequest, new Pager(1, 0, true));
        int totalPages = (int) Math.ceil((double) responseCalcTotal.getTotal() / 200);
        //执行分页查询
        List<RefundSearchResponse.RefundOrderDto> orderItemList = new ArrayList<>();
        for (int pageNo = totalPages - 1; pageNo >= 0; pageNo--) {
            RefundSearchResponse response = refundAPIAPI.search(refundSearchRequest, new Pager(200, pageNo, false));
            List<RefundSearchResponse.RefundOrderDto> pageOrderItems = response.getOrders();
            orderItemList.addAll(pageOrderItems);
        }

        return orderItemList;
    }


    //执行统计
    private List<StatisticsResultDTO> doStatistics(List<StockOutQueryResponse.OrderItem> orderItemList, List<RefundStockinResponse.OrderInfoDto> refundStockinOrderList,List<RefundSearchResponse.RefundOrderDto> refundOrderList,List<SalesStockoutPositionResponse.OrderInfoDto> filterOrder) {

        Map<CompositeKey, Data> statistics = new HashMap<>();
        //销售出库数据(不含淘系)
        //实际销售量=发货总量(来自销售出库单)-退货入库量(来自退货入库单)-仅退款量(来自退换单)
        if (StringUtils.isNotEmpty(orderItemList)) {
            for (StockOutQueryResponse.OrderItem order : orderItemList) {
                for (StockOutQueryResponse.DetailsItem orderDetails : order.getDetails()) {
                    CompositeKey key = new CompositeKey(orderDetails.getSpecNo(), order.getWarehouseNo(), order.getWarehouseName(), order.getShopNo(), order.getShopName(), orderDetails.getGoodsNo(), orderDetails.getSpecName());
                    statistics.putIfAbsent(key, new Data(BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0),BigDecimal.valueOf(0)));
                    //发货数量、发货单价*发货数量、发货成本、0、0、发货数量
                    statistics.get(key).addSales(orderDetails.getGoodsCount(), orderDetails.getSharePrice().multiply(orderDetails.getGoodsCount()), orderDetails.getTotalAmount(), BigDecimal.valueOf(0),BigDecimal.valueOf(0),orderDetails.getGoodsCount());
                }
            }
        }
//        //经过滤的淘系销售出库数据
//        if (StringUtils.isNotEmpty(filterOrder)) {
//            for (SalesStockoutPositionResponse.OrderInfoDto order : filterOrder) {
//                for (SalesStockoutPositionResponse.OrderDetailInfoDto orderDetails : order.getDetailList()) {
//                    CompositeKey key = new CompositeKey(orderDetails.getSpecNo(), order.getWarehouseNo(),"", "0002","天猫", orderDetails.getGoodsNo(), orderDetails.getSpecName());
//                    statistics.putIfAbsent(key, new Data(BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0),BigDecimal.valueOf(0)));
//                    //发货数量、发货单价*发货数量、发货成本、0、0、发货数量
//                    statistics.get(key).addSales(orderDetails.getNum(), orderDetails.getSharePrice().multiply(orderDetails.getNum()), BigDecimal.valueOf(0), BigDecimal.valueOf(0),BigDecimal.valueOf(0),orderDetails.getNum());
//                }
//            }
//        }
        //退货入库数据
        if (StringUtils.isNotEmpty(refundStockinOrderList)) {
            for (RefundStockinResponse.OrderInfoDto refundOrder : refundStockinOrderList) {
                for (RefundStockinResponse.OrderDetailInfoDto orderDetailInfo : refundOrder.getDetailList()) {
                    CompositeKey key = new CompositeKey(orderDetailInfo.getSpecNo(), refundOrder.getWarehouseNo(), refundOrder.getWarehouseName(), refundOrder.getShopNo(), refundOrder.getShopName(), orderDetailInfo.getGoodsNo(), orderDetailInfo.getSpecName());
                    statistics.putIfAbsent(key, new Data(BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0)));
                    //0，0，0，退货金额、退货数量、退货数量
                    statistics.get(key).addSales(BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), orderDetailInfo.getRefundAmount(),orderDetailInfo.getNum(),orderDetailInfo.getNum().negate());

                }
            }
        }
        //退换单数据
        if (StringUtils.isNotEmpty(refundOrderList)) {
            for (RefundSearchResponse.RefundOrderDto refundOrder : refundOrderList) {
                for (RefundSearchResponse.RefundOrderInfoDto orderDetailInfo : refundOrder.getDetailList()) {
                    CompositeKey key = new CompositeKey(orderDetailInfo.getSpecNo(), refundOrder.getReturnWarehouseNo(), "", refundOrder.getShopNo(), "", orderDetailInfo.getGoodsNo(), orderDetailInfo.getSpecName());
                    statistics.putIfAbsent(key, new Data(BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0)));
                    //0，0，0，0，0，仅退款量
                    statistics.get(key).addSales(BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0), BigDecimal.valueOf(0),BigDecimal.valueOf(0),orderDetailInfo.getNum().negate());

                }
            }
        }

        List<StatisticsResultDTO> result = new ArrayList<StatisticsResultDTO>();
        statistics.forEach(((compositeKey, data) -> {
            StatisticsResultDTO item = new StatisticsResultDTO();
            item.setSpecNo(compositeKey.getSpecNo());
            item.setWarehouseNo(compositeKey.getWarehouseNo());
            item.setWarehouseName(compositeKey.getWarehouseName());
            item.setShopNo(compositeKey.getShopNo());
            item.setShopName(compositeKey.getShopName());
            item.setGoodsNo(compositeKey.getGoodsNo());
            item.setSpecName(compositeKey.getSpecName());
            item.setSalesQuantity(data.getSalesQuantity());
            item.setSalesAmount(data.getSalesAmount());
            item.setSalesCost(data.getSalesCost());
            item.setRefundAmount(data.getRefundAmount());
            item.setRefundQuantity(data.getRefundQuantity());
            item.setActualSalesQuantity(data.getActualSalesQuantity());
            result.add(item);
        }));

        return result;

    }

    //维度实体
    class CompositeKey {

        private String specNo;//商家编码
        private String warehouseNo;
        private String warehouseName;
        private String shopNo;
        private String shopName;
        private String goodsNo;
        private String specName;//规格名称


        public CompositeKey(String specNo, String warehouseNo, String warehouseName, String shopNo, String shopName, String goodsNo, String specName) {
            this.specNo = specNo;
            this.warehouseName = warehouseName;
            this.warehouseNo = warehouseNo;
            this.shopName = shopName;
            this.shopNo = shopNo;
            this.goodsNo = goodsNo;
            this.specName = specName;
        }

        public String getSpecNo() {
            return specNo;
        }

        public String getWarehouseNo() {
            return warehouseNo;
        }

        public String getWarehouseName() {
            return warehouseName;
        }

        public String getShopNo() {
            return shopNo;
        }

        public String getShopName() {
            return shopName;
        }

        public String getGoodsNo() {
            return goodsNo;
        }

        public String getSpecName() {
            return specName;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            CompositeKey that = (CompositeKey) o;
            return Objects.equals(specNo, that.specNo) &&
                    Objects.equals(warehouseNo, that.warehouseNo) &&
                    Objects.equals(shopNo, that.shopNo) &&
                    Objects.equals(goodsNo, that.goodsNo);
        }

        @Override
        public int hashCode() {
            return Objects.hash(specNo, warehouseNo, shopNo, goodsNo);
        }
    }

    //统计值实体
    class Data {
        private BigDecimal salesQuantity;
        private BigDecimal salesAmount;

        private BigDecimal salesCost;

        private BigDecimal refundAmount;

        private BigDecimal refundQuantity;

        private BigDecimal actualSalesQuantity;

        public Data(BigDecimal salesQuantity, BigDecimal salesAmount, BigDecimal salesCost, BigDecimal refundAmount, BigDecimal refundQuantity, BigDecimal actualSalesQuantity) {
            this.salesQuantity = salesQuantity;
            this.salesAmount = salesAmount;
            this.salesCost = salesCost;
            this.refundAmount = refundAmount;
            this.refundQuantity=refundQuantity;
            this.actualSalesQuantity=actualSalesQuantity;

        }

        public void addSales(BigDecimal quantity, BigDecimal amount, BigDecimal cost, BigDecimal refund,BigDecimal refundQuantity, BigDecimal actualSalesQuantity) {
            this.salesQuantity = this.salesQuantity.add(quantity);
            this.salesAmount = this.salesAmount.add(amount);
            this.salesCost = this.salesCost.add(cost);
            this.refundAmount = this.refundAmount.add(refund);
            this.refundQuantity=this.refundQuantity.add(refundQuantity);
            this.actualSalesQuantity=this.actualSalesQuantity.add(actualSalesQuantity);
        }

        public BigDecimal getSalesAmount() {
            return salesAmount;
        }

        public BigDecimal getSalesQuantity() {
            return salesQuantity;
        }

        public void setSalesAmount(BigDecimal salesAmount) {
            this.salesAmount = salesAmount;
        }

        public void setSalesQuantity(BigDecimal salesQuantity) {
            this.salesQuantity = salesQuantity;
        }

        public BigDecimal getRefundAmount() {
            return refundAmount;
        }

        public void setRefundAmount(BigDecimal refundAmount) {
            this.refundAmount = refundAmount;
        }

        public BigDecimal getSalesCost() {
            return salesCost;
        }

        public void setSalesCost(BigDecimal salesCost) {
            this.salesCost = salesCost;
        }

        public BigDecimal getRefundQuantity() {
            return refundQuantity;
        }

        public void setRefundQuantity(BigDecimal refundQuantity) {
            this.refundQuantity = refundQuantity;
        }

        public BigDecimal getActualSalesQuantity() {
            return actualSalesQuantity;
        }

        public void setActualSalesQuantity(BigDecimal actualSalesQuantity) {
            this.actualSalesQuantity = actualSalesQuantity;
        }

    }

}
